package com.k2data.Utils;

import java.security.MessageDigest;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSONObject;
import com.k2data.platform.common.utils.http.RequestException;
import com.k2data.platform.common.utils.http.Requests;
import com.k2data.platform.common.utils.http.SimpleHttpResponse;;

/**
 * 
 * @author pc
 *
 */
public class AssetUtils {
	private static final Log LOG = LogFactory.getLog(AssetUtils.class);

	public static String sysid(Map<String, String> compoundId) {
		return map2MD5(sortCompoundId(compoundId));
	}

	/**
	 *
	 * @param compoundId
	 * @return
	 */

	protected static LinkedHashMap<String, String> sortCompoundId(Map<String, String> compoundId) {
		TreeMap<String, String> compoundIdTree = new TreeMap<String, String>();
		Set<String> set = compoundId.keySet();
		for (String s : set) {
			compoundIdTree.put(s, compoundId.get(s));
		}
		set = compoundIdTree.keySet();
		LinkedHashMap<String, String> sortedCompoundId = new LinkedHashMap<String, String>();
		for (String s : set) {
			sortedCompoundId.put(s, compoundId.get(s));
		}
		return sortedCompoundId;
	}

	/**
	 * 
	 * @param map
	 * @return
	 */

	private static String map2MD5(LinkedHashMap<String, String> map) {
		String inStr = map.toString();
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (Exception e) {
			System.out.println(e.toString());
			e.printStackTrace();
		}
		char[] charArray = inStr.toCharArray();
		byte[] byteArray = new byte[charArray.length];

		for (int i = 0; i < charArray.length; i++)
			byteArray[i] = (byte) charArray[i];
		byte[] md5Bytes = md5.digest(byteArray);
		StringBuffer hexValue = new StringBuffer();
		for (int i = 0; i < md5Bytes.length; i++) {
			int val = ((int) md5Bytes[i]) & 0xff;
			if (val < 16)
				hexValue.append("0");
			hexValue.append(Integer.toHexString(val));
		}
		return hexValue.toString();
	}

	/**
	 * 
	 * @return
	 * @throws SQLException
	 */
	public static Map<String, String> getPublishedAssetsId(Connection conn)  {

		Map<String, String> map = new ConcurrentHashMap<String, String>();

//		Connection conn = MysqlService.getConnection("192.168.130.55", 13306, "k2db", "root", "passw0rd");
		String sql = "select id from k2db.asset where status='PUBLISHED'";
		try{
		ResultSet rs = MysqlService.executeQuery(conn, sql);

		try {
			while (rs.next()) {
				// q.add(rs.getString(1));
				map.put(rs.getString(1), "0");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		rs.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		return map;

	}

	/**
	 * 
	 * @param url
	 * @param assetBody
	 * @return
	 */

	public static int registerAsset(String url, String assetBody) {
		LOG.info("add asset:" + assetBody.toString());
		StringBuilder requestUrl = new StringBuilder();
		requestUrl.append(url);
//		requestUrl.append("/assets");
		SimpleHttpResponse response = null;
		Map<String, String> HEADER = new HashMap<String, String>();
		HEADER.put("Accept", "application/json");
		HEADER.put("Content-Type", "application/json");
		try {
			response = Requests.post(requestUrl.toString(), HEADER, assetBody);
			return response.getStatusCode();
		} catch (RequestException e) {
			LOG.error("Failed add asset:" + assetBody.toString());
			e.printStackTrace();
			return -1;
		}

	}

	/**
	 * 
	 * @param asset
	 * @param registeredAsset
	 * @param maxCheckNum
	 * @param checkIntervalMs
	 * @return
	 * @throws InterruptedException
	 */
	public static boolean waitAssetPublished(String asset, ConcurrentLinkedQueue<String> registeredAsset,
			int maxCheckNum, long checkIntervalMs) throws InterruptedException {
		int i = 0;
		while (i <= maxCheckNum) {

			if (registeredAsset.contains(asset)) {

				return true;
			}
			Thread.sleep(checkIntervalMs);
			i++;
		}

		return false;
	}

	/**
	 * 
	 * @param assetUrl
	 * @param assetId
	 * @return
	 */
	public static int isAssetExisting(String assetUrl, String assetId) {
		SimpleHttpResponse response = null;
		try {
			response = Requests.get(assetUrl + "/" + assetId);
			if (response != null) {

				return response.getStatusCode();
			} else {
				LOG.error("find Asset request return null: " + assetUrl + "/" + assetId);
				return -1;
			}
		} catch (RequestException e) {
			LOG.error("find asset request got exception." + " " + e.getMessage());
			LOG.error("Check if the KMX SDM Service avaliable:" + assetUrl + "/" + assetId);
			return -1;
		}
	}

	/**
	 * 
	 * @param assetUrl
	 * @param assetId
	 * @param maxCheckNum
	 * @param checkIntervalMs
	 * @return
	 */

	public static boolean waitAssetPublished(String assetUrl, String assetId, int maxCheckNum, long checkIntervalMs) {
		SimpleHttpResponse response = null;
		int checkFlag = 0;
		while (checkFlag <= maxCheckNum) {
			try {
				response = Requests.get(assetUrl + "/" + assetId);
				int rc = response.getStatusCode();
				if (rc == 200) {
					JSONObject payload = JSONObject.parseObject(response.getText());
					if ("PUBLISHED".equalsIgnoreCase(payload.getJSONObject("asset").getString("status"))) {
						return true;
					}
				}
			} catch (RequestException e) {
				LOG.info("find asset request got exception:" + assetId.toString() + " " + e.getMessage());
				LOG.info("Check if the KMX SDM Service avaliable:" + assetUrl);
			}

			checkFlag++;
			Utils.waiting(checkIntervalMs);
		}
		return false;
	}

	/**
	 *
	 * @param kmxAssetUrl
	 * @param assetId
	 * @param asset
	 * @param checkTimes
	 * @param checkInterval
	 * @return
	 */
	
	
	public static boolean autoRegisterAsset(String kmxAssetUrl, String assetId, JSONObject asset, int checkTimes,
			long checkInterval) {
		int isAssetExiting = AssetUtils.isAssetExisting(kmxAssetUrl, assetId);
		if (isAssetExiting == 404) {
			int code = AssetUtils.registerAsset(kmxAssetUrl, asset.toJSONString());
			if (code == 201 || code == 409) {
				if (!AssetUtils.waitAssetPublished(kmxAssetUrl, assetId, checkTimes, checkInterval)) {
					LOG.error("Asset status always PRE-PUBLISHED ,Check if the KMX SDM Service avaliable:" + kmxAssetUrl
							+ "/" + assetId);
					return false;
				} else {
					LOG.info("Asset " + assetId + " registered successful");
					return true;
				}
			} else {
				LOG.error("Register Asset got exception,check if the KMX SDM Service avaliable: " + kmxAssetUrl);
				LOG.error("Asset contents:" + asset.toJSONString());
				return false;
			}

		} else if (isAssetExiting == 200) {
			if (!AssetUtils.waitAssetPublished(kmxAssetUrl, assetId, checkTimes, checkInterval)) {
				LOG.error("Asset status always PRE-PUBLISHED ,Check if the KMX SDM Service avaliable:" + kmxAssetUrl
						+ "/" + assetId);
				return false;
			} else {
				LOG.info("Asset " + assetId + " registered successful");
				return true;
			}
		} else {
			LOG.error("SDM service got unexpected exception,please check it:" + kmxAssetUrl + "/" + assetId);
			return false;
		}
	}

	public static void main(String[] args) throws SQLException, InterruptedException {
		JSONObject c=new JSONObject();
		c.put("factory_id", "993");
		c.put("equipment_id", "0");
		c.put("machine_id", "0");
		c.put("datatype", "0");
		c.put("channel_type", "4");
		c.put("channel_id", "7");
		
		JSONObject asset=new JSONObject();
		asset.put("compoundId", c);
		asset.put("fieldGroupId", "c_sta");
		Map<String,String> b=new HashMap<String,String>();
		b.put("factory_id", "993");
		b.put("equipment_id", "0");
		b.put("machine_id", "0");
		b.put("datatype", "0");
		b.put("channel_type", "4");
		b.put("channel_id", "7");
		
		
		autoRegisterAsset("http://192.168.130.62:8081/data-service/v2/assets",sysid(b),asset,20,400);
		
		
		

	}

	
	
	
}
